package com.simple.deploy.service;

import com.simp.expection.GlobalException;
import com.simp.page.R;
import com.simp.utils.CommonUtils;
import com.simple.deploy.constant.DeployConstant;
import com.simple.deploy.vo.DeployVo;
import com.simple.deploy.vo.FileVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author pan.shun
 * @since 2022/3/17 15:07
 */
@Slf4j
@Component
public class DeployService {
    /**
     * 后端部署路径
     */
    @Value("${project-file-path:null}")
    private String projectFilePath;

    /**
     * tomcat 的webApp路径
     */
    @Value("${tomcat-file-path:null}")
    private String tomcatFilePath;


    public R getFileList() {
        Map<String, List<FileVo>> fileMap = new ConcurrentHashMap<>();
        List<FileVo> projectFileList = new ArrayList<>(16);
        List<FileVo> tomcatFilePathList = new ArrayList<>(16);
        fileMap.put("projectFile", projectFileList);
        fileMap.put("tomcatFile", tomcatFilePathList);
        save(projectFileList, projectFilePath);
        save(tomcatFilePathList, tomcatFilePath);

        // 集合降序
        projectFileList.sort((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime()));
        tomcatFilePathList.sort((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime()));
        return R.success(fileMap);
    }

    private void save(List<FileVo> list, String filePath) {
        File[] projectFiles = new File(filePath).listFiles();
        if (null != projectFiles) {
            for (File f : projectFiles) {
                FileVo build = FileVo.builder()
                        .fileName(f.getName())
                        .createTime(CommonUtils.getFileCreateTime(f.getAbsolutePath()))
                        .size(CommonUtils.fileSizeFormat(f.length()))
                        .fileType(f.isDirectory() ? "目录" : "文件")
                        .status(f.isDirectory() ? 0 : 1)
                        .extension(getFileExtension(f.getName()))
                        .build();
                list.add(build);
            }
        }
    }

    private String getFileExtension(String fileName) {
        if (fileName.contains(".")) {
            return fileName.substring(fileName.lastIndexOf(".") + 1);
        } else {
            return "";
        }
    }


    public R queryFileContent(DeployVo deployVo) {
        if (StringUtils.isEmpty(deployVo.getFileName())) {
            throw new GlobalException("文件名不能为空");
        }
        if (deployVo.getFileName().contains(".jar")) {
            throw new GlobalException("jar包不能查看");
        }

        if (DeployConstant.TYPE.BACK_SERVICE.equals(deployVo.getType())) {
            // 后端
            return queryFileContent(projectFilePath, deployVo.getFileName());
        } else {
            // 前端
            return queryFileContent(tomcatFilePath, deployVo.getFileName());
        }
    }

    private R queryFileContent(String filePath, String fileName) {
        File file = new File(filePath + fileName);
        if (file.exists() && file.isFile()) {
            String fileContent = CommonUtils.getFileContent(file);
            return R.success(fileContent);
        } else {
            throw new GlobalException("文件内容查询失败");
        }
    }

    public R uploadFile(MultipartFile multipartFile, DeployVo deployVo) {
        if (DeployConstant.TYPE.BACK_SERVICE.equals(deployVo.getType())) {
            return upload(multipartFile, projectFilePath);
        } else {
            return upload(multipartFile, tomcatFilePath);
        }

    }

    private R upload(MultipartFile multipartFile, String filePath) {
        File file = new File(filePath + multipartFile.getOriginalFilename());
        try {
            multipartFile.transferTo(file);
            return R.success(null, "上传成功");
        } catch (IOException e) {
            throw new GlobalException("文件上传失败");
        }
    }

    public R removeFile(DeployVo deployVo) {
        if (DeployConstant.TYPE.BACK_SERVICE.equals(deployVo.getType())) {
            // 后端
            return deleteFile(projectFilePath, deployVo.getFileName());
        } else {
            // 前端
            return deleteFile(tomcatFilePath, deployVo.getFileName());
        }
    }

    private R deleteFile(String filePath, String fileName) {
        File file = new File(filePath + fileName);
        if (file.exists() && file.isFile()) {
            file.delete();
            return R.success();
        } else {
            throw new GlobalException("文件删除失败");
        }
    }

    @Async
    public void executeCommandAsync(String cmd) {
        CommonUtils.executeCommand(cmd);
    }

    public R reNameFileName(DeployVo deployVo) {
        if (DeployConstant.TYPE.BACK_SERVICE.equals(deployVo.getType())) {
            // 后端
            return renameFile(projectFilePath, deployVo.getFileName(), deployVo.getNewFileName());
        } else {
            // 前端
            return renameFile(tomcatFilePath, deployVo.getFileName(), deployVo.getNewFileName());
        }
    }

    private R renameFile(String filePath, String oldFileName, String newFileName) {
        try {
            File file = new File(filePath + oldFileName);
            File newFile = new File(file.getParent() +File.separator+ newFileName);
            file.renameTo(newFile);
            return R.success();
        } catch (Exception e) {
            throw new GlobalException("文件名修改失败");
        }

    }

    public R unZipFile(DeployVo deployVo) {
        if (DeployConstant.TYPE.BACK_SERVICE.equals(deployVo.getType())) {
            // 后端
            return unZip(projectFilePath, deployVo.getFileName());
        } else {
            // 前端
            return unZip(tomcatFilePath, deployVo.getFileName());
        }
    }

    private R unZip(String filePath, String fileName) {
        try {
            File file = new File(filePath + fileName);
            CommonUtils.unzipFile(file, file.getParent());
            return R.success();
        } catch (Exception e) {
            throw new GlobalException("解压异常");
        }
    }

}
